/* 
 * File:   Lista.cpp
 * Author: Arturo
 * 
 * Created on November 27, 2010, 5:35 PM
 */

#include "Lista.h"

Lista::Lista() : Head(NULL), Current(NULL), idmax(0)
{
}

Lista::~Lista()
{
    if (this->Head)
    {
        this->Head->KillMe();
    }
}

bool Lista::Find(int id)
{
    Nodo* p = this->Head;

    while (p) {
        if (p->Dato->GetId() == id) {
            this->Current = p;
            return true;
        }

        p = p->Sig;
    }
    
    // Reseteo el Current a la cabeza.
    this->Current = this->Head;

    return false;
}

bool Lista::Add(Object* dato)
{
    Nodo** p;

    // Si no tiene ID le asigno el siguiente correlativo.
    if (!dato->GetId()) {
        dato->SetId(++idmax);
    }
    
    // Si lo encuentra, no lo inserta.
    if (Find(dato, p)) {
        return false;
    }


    // Creo el nuevo nodo.
    Nodo* nuevo = new Nodo(dato);
    // El siguiente del nuevo nodo es igual al Nodo* almacenado en el puntero p.
    nuevo->Sig = *p;
    // Al Nodo* almacenado en el puntero p le asigno el nuevo Nodo*.
    *p = nuevo;

    // Reseteo el Current a la cabeza.
    this->Current = this->Head;
    
    idmax = dato->GetId();

    return true;
}

bool Lista::Remove(Object* dato)
{
    Nodo** p;

    // Si no lo encuentra, no quito nada.
    if (!Find(dato, p)) {
        return false;
    }

    Nodo* tmp = *p;

    *p = (*p)->Sig;

    delete tmp;

    // Reseteo el Current a la cabeza.
    this->Current = this->Head;

    return true;
}

Nodo* Lista::Next()
{
    if (this->Current) this->Current = Current->Sig;
    
    return this->Current;
}

void Lista::Reset()
{
    this->Current = this->Head;
}


string Lista::ToString()
{
    string r;

    Nodo* p = this->Head;
    while (p) {
        r += p->Dato->ToString() + '\n';
        p = p->Sig;
    }

    return r;
}

ostream& operator<<(ostream &os, const Lista &l)
{
    Nodo* p = l.Head;

    while(p) {
        os << p->Dato->ToString() + '\n';
        p = p->Sig;
    }

    return os;
}

bool Lista::Find(Object* dato, Nodo** &p)
{
    // Empiezo en la cabeza.
    p = &this->Head;

    // Compruebo que tenga cabeza para meterme a el y comparar su dato.
    while (*p && (*p)->Dato->GetId() < dato->GetId())
    {
        p = &((*p)->Sig);
    }

    // Compruebo que tenga cabeza para meterme a el y comprar si lo encontre.
    return *p && (*p)->Dato->GetId() == dato->GetId();
}
